/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.transas.zorlog.ui.graph;

import com.transas.zorlog.data.DataSource;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

/**
 * Graph holds values from DataSource and draws them as polyline with given color
 * @author amalikov
 */
public class Graph {

	public Graph(DataSource ds, String name, Color color) {
		this.name = name;
		this.color = color;
		values = ds.getValues(name);
		bit = ds.getAttribute(ds.getHandle(name), "bit").equalsIgnoreCase("true");
		yoffset = 0;
	}

	public double getMin() {
		double min = (values.length > 0) ? values[0] : 0;
		for (int i = 1; i < values.length; ++i)
			min = Math.min(min, values[i]);
		return min;
	}

	public double getMax() {
		double max = (values.length > 0) ? values[0] : 0;
		for (int i = 1; i < values.length; ++i)
			max = Math.max(max, values[i]);
		return max;
	}
	
	public double getValue(int index) {
		return (index < values.length) ? values[index] : 0;
	}
	
	public String getName() {
		return name;
	}
	
	public Color getColor() {
		return color;
	}
	
	public void draw(Graphics g, Rectangle rect, double min, double max, int begin, int end) {
		if (isBit()) {
			drawBit(g, rect, yoffset, begin, end);
			return;
		}
		
		if (values.length == 0)
			return;
		
		end = Math.min(Math.max(end, 0), values.length);
		begin = Math.min(Math.max(begin, 0), values.length - 1);
		
		if (end <= begin)
			end = begin + 1;

		double yscale = rect.height / (max - min);
		double delta = (double) (end - begin) / (double) rect.width;
		
		int[] xPoints = new int[end - begin];
		int[] yPoints = new int[end - begin];
		
		int n = 0;
		for (int i = begin; i < end; ++i, ++n) {
			xPoints[n] = (int) (n / delta + 0.5) + rect.x;
			yPoints[n] = rect.height - (int) ((values[i] - min) * yscale + 0.5) + rect.y;
		}
		
		g.setColor(color);
		g.drawPolyline(xPoints, yPoints, n);
	}

	private void drawBit(Graphics g, Rectangle rect, int y, int begin, int end) {
		if (values.length == 0)
			return;
		
		end = Math.min(Math.max(end, 0), values.length);
		begin = Math.min(Math.max(begin, 0), values.length - 1);
		
		if (end <= begin)
			end = begin + 1;

		double delta = (double) (end - begin) / (double) rect.width;
		
		g.setColor(color);
		
		int n = 0;
		boolean lastV = false;
		int lastN = 0;
		for (int i = begin; i < end; ++i, ++n) {
			boolean curV = values[i] > 0;
			if (curV != lastV || i == end - 1) {
				int x0 = (int) (lastN / delta + 0.5) + rect.x;
				int x1 = (int) (n / delta + 0.5) + rect.x;
				
				if (!lastV)
					g.drawLine(x0, y + rect.y, x1, y + rect.y);
				else
					g.fillRect(x0, y - 2, x1 - x0, 5);
				
				lastN = n;
				lastV = curV;
			}
		}
	}
	
	public boolean isBit() {
		return bit;
	}
	
	public void setYOffset(int yoffset) {
		this.yoffset = yoffset;
	}
	
	public int getYOffset() {
		return yoffset;
	}

	private final String name;
	protected final Color color;
	private boolean bit;
	private int yoffset;	// used only if bit == true
	
	protected double[] values;
}
